package log

//Logger Interface about output behaviors of log handler.
type Logger interface {
	//start logging message
	Ctx() ContextAllowTar

	//start logging message with specify log level
	TRC() ContextAllowTar
	DBG() ContextAllowTar
	INF() ContextAllowTar
	WAR() ContextAllowTar
	ERR() ContextAllowTar
	FAT() ContextAllowTar
}

//LoggerHandler Interface of log handler.
//LoggerHandler is an abstract definition. A log handler is a object instance
//that can be configured with some properties. And provides interfaces to output
//log message.
type LoggerHandler interface {
	//LoggerHandler is a superset of Logger.
	Logger

	//clone a new LoggerHandler instance with same configuration.
	//context will not be clone.
	Clone() LoggerHandler

	//bind time format function.
	//time format function is used to format time "now" for outputting log message.
	//if param f is nil, log message have no time string.
	BindTimeFmt(f FuncTimeFmt)

	//set separator of log format. default separator is "|".
	SetSeparator(sep string)

	//get current log level
	Level() int
	//set log level for handler.
	SetLevel(l int)

	//add a output target to handler.
	AddTarget(t Target)
	//del a output target from handler.
	DelTarget(name string)

	//add a prefix.
	//every prefix string will be joined to every log message.
	//param key is a inner identifier. only param value will be joined to message.
	AddPrefix(key, val string)
	//delete a prefix by key.
	DelPrefix(key string)

	//switch whether outputting code line in log message.
	SwitchCodeLine(b bool)

	//switch whether use json to assemble log message.
	SwitchJSONAssemble(b bool)

	//release log handler resources
	Release()
}

//Target is abstract interface of output target definition.
type Target interface {
	//name of target.
	Name() string

	//using count of target
	IncrUsing()

	//check whether target need ignore a log message.
	//param l is log level.
	IsIgnore(l int) bool

	//output message
	Put(msg string)

	//close target resources
	Close()
}

var globalHandler LoggerHandler
var defaultTargets = []Target{Stdout}

func init() {
	globalHandler = NewHandler()
}

//GlobalHandler return the global handler.
//It is the handler accepting static Logger function.
func GlobalHandler() LoggerHandler {
	return globalHandler
}

//SetGlobalHandler return the global handler.
func SetGlobalHandler(h LoggerHandler) {
	globalHandler = h
}

//Log is the start point of static calling to output log message.
func Log() Logger {
	return globalHandler
}

//TRC can be a start point of static calling to log with trace level.
func TRC() Context {
	return Log().TRC()
}

//DBG can be a start point of static calling to log with debug level.
func DBG() Context {
	return Log().DBG()
}

//INF can be a start point of static calling to log with info level.
func INF() Context {
	return Log().INF()
}

//WAR can be a start point of static calling to log with warning level.
func WAR() Context {
	return Log().WAR()
}

//ERR can be a start point of static calling to log with error level.
func ERR() Context {
	return Log().ERR()
}

//FAT can be a start point of static calling to log with fatal level.
func FAT() Context {
	return Log().FAT()
}

//SetDefaultTargets set target list for default. It is used for creating logger handler.
func SetDefaultTargets(ts []Target) {
	defaultTargets = append([]Target{}, ts...)
}

//GetDefaultTargets get target list from default
func GetDefaultTargets() []Target {
	return defaultTargets
}
